<?php
namespace util;


function build_json($targets, $xml): void {
    $datas = [];
    foreach ($targets as $target) $datas += build_json_target($xml, $target);
    echo json_encode($datas, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
}

// $target: [3, "gcd", ['gcd','gcd', 'cd']];
function build_json_target($xml, $target){
    if (count($target) < 3) exit("json_build_target 脚本生成参数错误!!!!!!!!!!!!!!!\n");
    if (count($target[2]) < 1) exit("json_build_target 脚本生成字段不能为空!!!!!!!!!!!\n");

    $targetXmlIdx   = $target[0];
    $targetXmlKey   = $target[1];
    $fields         = $target[2];

    $xmlData        = $xml[$targetXmlIdx - 1];
    $targetData     = get_data_by_xml_key_field($xmlData, $targetXmlKey, $fields);

    foreach ($fields as $fieldIdx => $field) {
        if (!is_array($field) || $fieldIdx == 'CLI_FIELDS') continue;
        // 处理子数据
        $subTargetData = build_json_target($xml, $field);
        foreach ($subTargetData as $subXmlKey => $subXmlData) {
            foreach ($targetData[$targetXmlKey] as $targetKey => $targetVal) {
                if (is_array(reset($targetVal))) {
                    foreach ($targetVal as $targetFieldKey => $targetFieldVal) {
                        $keyForSub = $targetFieldVal[$fieldIdx];
                        unset($targetData[$targetXmlKey][$targetKey][$targetFieldKey][$fieldIdx]);
                        if (!empty($subXmlData[$keyForSub]))
                            $targetData[$targetXmlKey][$targetKey][$targetFieldKey][$subXmlKey] = $subXmlData[$keyForSub];
                        else
                            $targetData[$targetXmlKey][$targetKey][$targetFieldKey][$subXmlKey] = [];
                    }
                } else {
                    $keyForSub = $targetVal[$fieldIdx];
                    unset($targetData[$targetXmlKey][$targetKey][$fieldIdx]);
                    if (!empty($subXmlData[$keyForSub]))
                        $targetData[$targetXmlKey][$targetKey][$subXmlKey] = $subXmlData[$keyForSub];
                    else
                        $targetData[$targetXmlKey][$targetKey][$subXmlKey] = [];
                }
            }
        }
    }
    return $targetData;
}

// 根据子表索引 字段 key字段取数据
// $target: [3, "gcd", ['gcd','gcd', 'cd']];
// $targetXmlKey: "gcd"
// $fields: ['gcd','gcd', 'cd']
function get_data_by_xml_key_field($xmlData, $targetXmlKey, $fields) {
    $array      = [];
    $arrayTmp   = [];

    $keyField = $fields[0]; //作为 key 的字段(数组第1个)
    $keyFieldDataType = data_type($xmlData, $keyField); //key 的数据类型

    $keySubField = $fields[1]; //导出 json 时的数据的 key
    $fields = array_del($fields, $keyField);

    $cliFields = null;
    if (isset($fields['CLI_FIELDS'])) {
        // CLI_FIELDS客户端指定字段
        $cliFields = $fields['CLI_FIELDS'];
        $fields = array_del($fields, $cliFields);
    };

    for ($i = 3; $i < count($xmlData); $i++) {
        $keyVal = $xmlData[$i][$keyField];
        if ($keyVal !== '' && ($cliFields == null || array_in($cliFields, $keyVal))) {
            $data1 = [];
            foreach ($fields as $fieldIdx => $field) {
                if (is_array($field)) { //数据要从其它 sheet 获取, 这里获取 $fieldIdx 及对应的值
                    $data1[ $fieldIdx ] = $xmlData[ $i ][ $fieldIdx ];
                } else if (is_record($xmlData[$i][$field])) {
                    $data1[ $field ] = json_gen_record($xmlData[$i][$field]);
                } else {
                    if (is_numeric($xmlData[$i][$field])) {
                        $data1[$field] = $xmlData[$i][$field];
                    } else {
                        if (is_attr(trim($xmlData[$i][$field]))) {
                            $data1[$field] = json_gen_attr($xmlData[$i][$field]);
                        } else {
                            if (trim($xmlData[$i][$field]) != '')
                                $data1[$field] = $xmlData[$i][$field];
                            else if(data_type($xmlData, $field) == 'obj')
                                $data1[$field] = [];
                            else if(data_type($xmlData, $field) == 'int')
                                $data1[$field] = 0;
                            else
                                $data1[$field] = '';
                        }
                    }
                }
            }
            if (is_int($data1[ $keySubField ]) || is_string($data1[ $keySubField ]))
                $arrayTmp[ $keyVal ][ $data1[ $keySubField ] ] = $data1;
            else
                $arrayTmp[ $keyVal ][] = $data1;
        }
    }
    if ($keyFieldDataType == 'obj') {
        foreach ($arrayTmp as $k => $v) $array[$targetXmlKey][$k] = reset($v);
    } else {
        foreach ($arrayTmp as $k => $v) $array[$targetXmlKey][] = reset($v);
    }
    return $array;
}

function data_type($data, $field) {
    return $data[2][ $field ];
}

// 根据数组值删除数组元素，不保留索引
function array_del($array, $val) {
    $key = array_search($val, $array);
    if ($key !== false && $key !== '') unset($array[$key]);
    return $array;
}

// 返回数组值是否在数组里面，或者匹配子串
function array_in(array $array, $val): bool {
    if (in_array($val, $array)) return true;

    foreach ($array as $v) {
        if (strstr($val, $v)) return true;
    }
    return false;
}

function is_attr(string $str): bool {
    return preg_match("/^{\s*([a-z_]+)/", $str) > 0;
}

function is_record(string $str): bool {
    return strstr($str, "cond") || strstr($str, "gain") || strstr($str, "loss");
}


// 解析前端用记录
//{record_type, label, p1, p2, ...}
function json_gen_record($str): array {
    $list = explode("\n", $str);
    $record = [];
    foreach($list as $item0){
        if (empty($item0)) continue;

        $item = substr(trim($item0), 1, -1);
        preg_match_all("/\w+|\[.*?]+|\{.*?}+/", $item, $match);
        $match = $match[0];

        switch ($match[0]) {
            case "cond":
                if(isset($match[3]))
                    $record[] = array("type" => "cond", "label" => trim($match[1]), "target" => trim($match[2]), "target_value" => trim($match[3]));
                else
                    $record[] = array("type" => "cond", "label" => trim($match[1]), "target_value" => trim($match[2]));
                break;
            case "gain":
                if($match[1] == "item" || $match[1] == "item_notice_flag"){
                    $item = explode(",", trim(trim($match[2]), "{}"));
                    $expire = 0;
                    if(isset($item[3]) && str_contains($item[3], 'expire')){
                        $expire = (int)trim($item[4]);
                    };
                    $record[] = array("type" => "gain", "label" => trim($match[1]), "base_id" => (int)$item[0], "bind" => (int)trim($item[1]), "num" => (int)trim($item[2]), "expire" => $expire);
                }else
                    $record[] = array("type" => "gain", "label" => trim($match[1]), "num" => (int)trim($match[2]));
                break;
            case "loss":
                if($match[1] == "item" || $match[1] == "item_expire_first"){
                    $item = explode(",", trim(trim($match[2]), "{}"));
                    $record[] = array("type" => "loss", "label" => trim($match[1]), "base_id" => (int)$item[0], "bind" => (int)trim($item[1]), "num" => (int)trim($item[2]));
                }else
                    $record[] = array("type" => "loss", "label" => trim($match[1]), "num" => (int)trim($match[2]));
                break;
        }
    }

    return $record;
}

function json_gen_attr($str): array {
    $arr = [];
    $arr_split = preg_split("/({)|(\s*}\s*,\s*{)|(})/", $str, -1, PREG_SPLIT_NO_EMPTY);
    foreach($arr_split as $v) {
        $arr_explode = explode(",", $v);
        $label = trim($arr_explode[0]);
        $val = trim($arr_explode[1]);
        $arr[$label] = $val;
    }
    return $arr;
}


function erl_attr_convert(string $str): string {
    global $gAttrDesc;

    $label = [];
    $int = [];
    foreach ($gAttrDesc as $k => $v) {
        $label[] = '{'. $k . ',';
        $int[] = '{'. $v . ',';
    }

    return str_replace($label, $int, $str);
}

function erl_gen_record(string $str): string {
    $items = explode("\n", $str);

    $record = "";
    foreach($items as $item0) {
        if (empty($item0)) continue;

        $item = substr(trim($item0), 1, -1);

        preg_match_all("/\w+|\[.*?]+|\{.*?}+/", $item, $match);
        $match = $match[0];

        switch ($match[0]) {
            case "cond":
                if(isset($match[3]))
                    $record .= "#condition{label = ". trim($match[1]). ", target = ". trim($match[2]). ", target_value = ". trim($match[3]). "}, ";
                else
                    $record .= "#condition{label = ". trim($match[1]). ", target_value = ". trim($match[2]). "}, ";
                break;
            case "gain":
                $record .= "?GAIN(". trim($match[1]). ", ". trim($match[2]). "), ";
                break;
            case "loss":
                $record .= "?LOSS(". trim($match[1]). ", ". trim($match[2]). "), ";
                break;
        }
    }

    return '['. substr($record, 0, strlen($record) - 2). ']';
}
